<template>
  <div class="konva" ref="konvaDom"></div>
</template>

<script setup lang="ts">
import {onMounted, ref} from "vue";
import Konva from "konva";
import {konvaData} from "./data";

const konvaDom = ref();
let stage: any = null;
let layer: any = null;
let scale: number = 1;


function getDomWH() {
  const {clientWidth, clientHeight} = konvaDom.value;
  return {
    width: clientWidth,
    height: clientHeight
  }
}

function formatX(x: number) {
  return x - 942.2791662544423
}

function formatY(y: number) {
  return y - 2175.648233237631
}

function getAngle(x: number, y: number, centerX: number, centerY: number) {
  let angle = Math.atan2(y, x);
  if ( x < centerX && y >= centerY) {
    angle += 180;
  }

  if (x < centerX && y < centerY) {
    angle += 90;
  }

  if (x >= centerX && y >= centerY) {
    angle += 270;
  }
  return Math.floor(angle);
}

function drawLine(data: any) {
  const {line_index, coordinate} = data;
  const {starting_point, ending_point} = coordinate;
  let {X: startX, Y: startY} = starting_point;
  let {X: endX, Y: endY} = ending_point;
  startX = formatX(startX);
  startY = formatY(startY);
  endX = formatX(endX);
  endY = formatY(endY);
  const line = new Konva.Line({
    points: [startX, startY, endX, endY],
    stroke: 'black',
    lineCap: 'round',
    lineJoin: 'round',
    lineId: line_index
  });
  layer.add(line);
}

function drawCircle(data: any) {
  const {line_index, coordinate} = data;
  let {center, radius, starting_point, ending_point} = coordinate;
  let {X: startX, Y: startY} = starting_point;
  let {X: endX, Y: endY} = ending_point;
  startX = formatX(startX);
  startY = formatY(startY);
  endX = formatX(endX);
  endY = formatY(endY);
  let {X, Y} = center;
  X = formatX(X);
  Y = formatY(Y);
  const startAngle = getAngle(startX, startY, X, Y);
  const endAngle = getAngle(endX, endY, X, Y);
  console.log(startAngle, endAngle);
  let circle = new Konva.Shape({
    stroke: 'black',
    sceneFunc: function (context, shape) {
      context.beginPath();
      context.arc(X, Y, radius, startAngle, endAngle, false);
      context.lineCap = 'round';
      context.lineJoin = 'round';
      context.fillStrokeShape(shape);
    },
    lineId: line_index
  });
  layer.add(circle);
}

function drawKonva() {
  konvaData.forEach((item: any) => {
    switch (item.type) {
      case 'LINE':
        drawLine(item);
        break;
      case 'ARC':
        drawCircle(item);
        break;
    }
  });
}

function clickInfo(lineId: string) {
  const info = konvaData.find(({line_index}) => line_index === lineId);
  if (info) {
    alert(`line_index：${lineId}\ntype：${info.type}`);
  }
}

function bindEvent() {
  stage.on('wheel', (e: any) => {
    e.evt.preventDefault();
    stage.setAttrs(wheelStage(e, stage.getX(), stage.getY()));
    stage.batchDraw();
  });
  stage.on('mouseup', (e: any) => {
    let {lineId} = e.target.attrs;
    clickInfo(lineId);
  });
}

function wheelStage(e: any, x: number, y: number) {
  const {wheelDelta, deltalY, offsetX, offsetY} = e.evt;
  const wheelData = wheelDelta ? wheelDelta : deltalY * -40;
  const rateX: number = (offsetX - x) / scale;
  const rateY: number = (offsetY - y) / scale;
  if (wheelData > 0) {
    scale = Number((scale + 0.05).toFixed(2));
  } else {
    if (scale <= 0.2) {
      scale = 0.2;
      return;
    }
    scale = Number((scale - 0.05).toFixed(2));
  }
  const sx: number = (1 - scale) * rateX + offsetX - rateX;
  const sy: number = (1 - scale) * rateY + offsetY - rateY;

  return {
    x: sx,
    y: sy,
    scaleX: scale,
    scaleY: scale
  }
}
function initKonva() {
  const {width, height} = getDomWH();
  stage = new Konva.Stage({
    container: konvaDom.value,
    width,
    height,
    draggable: true
  });
  layer = new Konva.Layer();
  stage.add(layer);
  drawKonva();
  bindEvent();
  stage.draw();
}

onMounted(() => {
  initKonva();
});
</script>

<style scoped>
.konva {
  width: 100%;
  height: 100vh;
  border: 1px solid red;
}
</style>
